/**
 *
 *	@file worker.c
 *	@brief Worker implementa le funzionalità lato server del sistema NMAT.
 *
 *  Created on: Jan 24, 2010
 *  Author: Marco Luisi
 */

#include "worker.h"


char *dir_name;
char *i_pipe; //rinominare nel client
char *o_pipe;
char *cwdir;
char *username;
char *wdir;

DIR *dir;//rinominare in userdir?

int dim;
int i;
int go;
int in;
int out;
int pid;


//var matrici
int files_num;
int matrices_num;
int dim_mat;
int temp;
matrix_l *matlist = NULL;


struct dirent *file;


//var messaggi
matrix_t *matrices; //da cambiare!!!!!!!!!!1
message_t req;
message_t res;
int status;


volatile int cpid;// meglio int o char?
//volatile char *cpid;

//gestire sigpipe?

int main(int argc, char **argv) {

	printf("Worker DEBUG: worker avviato\n");
	cpid = atoi(argv[2]);//ricontrollare se serve int
	username = strdup(argv[1]);
	printf("Worker DEBUG: worker per %s:%d\n", username,cpid);

	init();
	go = 1;
	while(go){
		go = serve();
		// freeeee
	}

	return 0;
}// fine main


/**
 * La funzioni init provvede ad aprire le pipe di comunicazione
 * con il client e alla apertura della directory per l'utente.
 *
 */
void init() { //portare

	printf("DEBUG WORKER: init()\n");

	//setup gestione interruzioni
	struct sigaction term_action;
	bzero(&term_action, sizeof(term_action));
	term_action.sa_handler = term_handler;
	sigaction(SIGTERM, &term_action, NULL);

	struct sigaction int_action; //ignora altrimenti sigint su nmat uccide tutto in foreground
	bzero(&int_action, sizeof(int_action));
	int_action.sa_handler = SIG_IGN;
	sigaction(SIGINT, &int_action, NULL);

	//inizializzazione file di log
	//con data nome utente e pid
	//chiudere quello che è aperto nel server?

	//gestione pipe vs client
	EC_NULL_E(i_pipe = malloc(30 * sizeof(char)), "NMAT Worker errore"); // le dimensioni..
	sprintf(i_pipe, "%s%d", "../clientserver", cpid);//EC!
	printf("DEBUG WORKER i_pipe = !%s!\n", i_pipe);
	//temp?
	EC_M1_E(mkfifo(i_pipe,0666),"NMAT Worker errore mkfifo pipe");
	EC_M1_E(in = open(i_pipe, O_RDWR),"NMAT Worker errore pipe"); //controllare nonblock
	printf("DEBUG WORKER in=!%d!\n", in);
	//pipe in ingresso creata ed aperta


	EC_NULL_E(o_pipe = malloc(30 * sizeof(char)), "NMAT Worker errore"); // le dimensioni..
	sprintf(o_pipe, "%s%d", "../serverclient",cpid);
	EC_M1_E(out = open(o_pipe, O_WRONLY),"NMAT Worker errore pipe out");
	printf("DEBUG WORKER out=!%d!\n", out);
	//pipe pronte

	wdir = malloc(PATH_MAX * sizeof(char));
	//gestione directory
	printf("Worker DEBUG:getcwd=%s\n", wdir);//stablire dim massima username
	EC_NULL_E(dir_name = malloc(30 * sizeof(char)), "NMAT Worker errore");
	snprintf(dir_name, 30,"./%s",username);
	printf("Worker DEBUG: directory !%s!\n", dir_name);
	EC_NULL_E(dir = opendir(dir_name), "Worker: errore apertura dir");
	EC_M1_E(chdir(dir_name), "Worker: errore apertura dir");
	//dir utente aperta

	//log-> num files

	//inizializzazione array/lista per le matrici
	dim_mat = 5;
	EC_NULL_E(matrices = malloc(dim_mat * sizeof(matrix_t)),"NMAT WORKER errore memoria");
	printf("DEBUG WORKER: fine init()\n");
}//fine init


int serve(){
	int rcvd;
	int status;
	printf("Worker DEBUG: serve()\n");

	//usare un int per gestire il codice di receive
	EC_M1(rcvd = receive(in, &req));//con un errore si esce dal ciclo,ma non si comunica al client..
	printf("Worker DEBUG: dopo receive,rcvd = %d\n",rcvd);
	if(rcvd < 0){
		printf("Errore ricezione messaggio\n");
		return -1;
	}
	printf("Worker: ricevuto messaggio:\n");
	msgprint(&req);
	//ricevuto il messaggio, si esegue la richiesta
	switch(req.cmdcode) {

	case(_exi):{
		return _exi;
	}

	case(_list):{

	}

	case(_print):{

	}

	case(_save):{

	}

	case(_load):{
		load();
		break;
	}

	case(_new):{

	}

	case(_TRASP):{

	}

	case(_add):{

	}

	case(_sub):{

	}

	case(_mul):{

	}

	case(_del):{

	}

	}//fine switch comandi


	printf("Worker DEBUG: fine serve()\n");
	return 0;//cambiare in status


}

/**
 * @brief Funzione che esegue il comando load del client.
 * @param file
 * @return
 */

//status in generale è la risposta al comando interno di worker
int load(){

	status = loadFile(req.args[0]);
	printf("DEBUG loadFile=%d\n", status);
	if(status > 0) {
		res.argnum = 1;
		EC_NULL_E(res.args = (char**)malloc(1 * sizeof(char*)), "errore memoria");
		res.nnum = 0;
		res.cmdcode = status;
		//come si passa il
		res.args[0] = malloc(10 * sizeof(char));
		res.args[0] = status;

		send(out,&res);
	}

}



int fileToMat(){ //si passa l'array di struct, o direttamente la struct?



}


//come chiedere se sovrascr
int save(char* filename){ //con un int per l'opzione di riscrittura?
	int i;
	int fd;
	EC_M1_P(fd =open(filename,O_WRONLY),"NMAT Worker: errore i/o file");
	//creazione file qui?

	for(i = 0; i<matrices_num; i++){
		//EC_M1(matToFile(matrices[i]));

	}

	EC_M1_P(close(fd),"NMAT Worker: errore i/o file");

	return 0;
}


int add(message_t *msg){
	matrix_t *a;
	matrix_t *b;




}


//ALTRI SEGNALI?


void term_handler(int signum) {
	printf("WORKER DEBUG TERMHANDLER\n");
	kill((pid_t) cpid, SIGTERM);//invio sigterm al client
	close(in);
	unlink(i_pipe);//controllare
	perror("unlink i_pipe");
	printf("WORKER DEBUG  exit da termhandler\n");
	exit(0);
}








